package fun.ltool.core.excel.handler;

import fun.ltool.core.excel.annotation.ExcelEntity;
import fun.ltool.core.excel.annotation.ExcelField;
import fun.ltool.core.exceptions.ExcelException;
import fun.ltool.core.reflect.ReflectUtil;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Excel数据映射 数据行模式 处理类
 *
 * @author huangrongsong
 * @since 1.3
 */
public class ExcelDataRowHandler<D> extends ExcelBaseHandler<D> {

    public ExcelDataRowHandler(List<List<Object>> data, Class<D> excelDataClass, ExcelEntity excelEntity, Field[] fields) {
        super(data, excelDataClass, excelEntity, fields);
    }

    /**
     * 映射数据到实体集合
     *
     * @return 返回数据集合
     */
    public List<D> build() {
        // 表格数据
        List<List<Object>> list;
        // 映射后的数据
        List<D> resList = new ArrayList<>();
        // 处理读取行数
        list = getRowRangeLists();
        if (list == null || list.isEmpty()) {
            throw new ExcelException("未读取到数据，请检查数据是否为空和JavaBean注解是否正确配置");
        }
        // 表头数据
        List<Object> headers = getColumnRangeLists(list.get(0));
        if (headers.isEmpty()) {
            throw new ExcelException("读取表头数据为空，请检查数据");
        }
        list.subList(1, list.size()).forEach(row -> {
            // 处理读取列数
            List<Object> columns = getColumnRangeLists(row);
            D excelDataBean;
            try {
                // 实例化对象
                excelDataBean = excelMappingClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new ExcelException("实例化Excel映射对象失败", e);
            }
            // 判断是否有字段注解
            if (fields != null && fields.length > 0) {
                // 映射到bean
                ReflectUtil.buildClass(excelDataBean).executor(e -> e.fields(f -> {
                    for (int i = 0, headersSize = headers.size(); i < headersSize; i++) {
                        Object headerFieldName = headers.get(i);
                        // 判断表头字段
                        if (headerFieldName != null) {
                            // 过滤出注解配置名称
                            Field field = Arrays.stream(fields).filter(field1 -> {
                                String name = field1.getAnnotation(ExcelField.class).name();
                                return headerFieldName.toString().equals(name);
                            }).findFirst().orElse(null);
                            // 判断注解是否存在
                            if (field != null) {
                                Object value = null;
                                if (columns.size() > i) {
                                    value = columns.get(i);
                                }
                                ExcelField excelField = field.getAnnotation(ExcelField.class);
                                // 转换值
                                try {
                                    value = convertValue(value, field.getType(), excelField.typeConverter());
                                } catch (Exception ex) {
                                    if (excelField.isThrowError()) {
                                        throw new ExcelException(!excelField.message().isEmpty() ? excelField.message() : ex.getMessage(), ex);
                                    }
                                }
                                try {
                                    f.set(field.getName(), value);
                                } catch (Exception ex) {
                                    if (excelField.isThrowError()) {
                                        throw new ExcelException(!excelField.message().isEmpty() ? excelField.message() : "Excel实体映射赋值失败,实体: " + this.excelMappingClass.getName() + ",字段名：" + field.getName() + ",注解配置名称：" + excelField.name(), ex);
                                    }
                                }
                            } else {
                                // 没配置则走默认赋值
                                try {
                                    f.set(headerFieldName.toString(), columns.get(i));
                                } catch (Exception ignored) {
                                }
                            }
                        }
                    }
                })).build();
                resList.add(excelDataBean);
            } else {
                // 映射到bean
                ReflectUtil.buildClass(excelDataBean).executor(e -> e.fields(f -> {
                    for (int i = 0, headersSize = headers.size(); i < headersSize; i++) {
                        // 字段名
                        Object field = headers.get(i);
                        if (field != null) {
                            // 取值
                            if (columns.size() > i) {
                                f.set(field.toString(), columns.get(i));
                            }
                        }
                    }
                })).build();
                resList.add(excelDataBean);
            }
        });
        return resList;
    }


}
